package com.yulan.bankback.controller.bank;

import com.yulan.bankback.aop.Authorization;
import com.yulan.bankback.entity.constant.RiskConstant;
import com.yulan.bankback.entity.model.bank.BankUser;
import com.yulan.bankback.entity.result.RetCode;
import com.yulan.bankback.entity.result.RetResponse;
import com.yulan.bankback.entity.result.RetResult;
import com.yulan.bankback.service.bank.BankUserService;
import com.yulan.bankback.service.bank.OssService;
import com.yulan.bankback.service.bank.RedisService;
import com.yulan.bankback.service.bank.RiskService;
import com.yulan.bankback.util.IpUtil;
import com.yulan.bankback.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


@RestController
@RequestMapping("/user")
public class UserController implements InitializingBean {

    @Autowired
    private BankUserService bankUserService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private OssService ossService;

    @Autowired
    private RiskService riskService;

    private static final long TEN_DAY = 10 * 60 * 60 * 24 * 1000L;

    @Autowired
    @Qualifier("baseThreadPool")
    private ThreadPoolExecutor executor;

    @Authorization({"admin", "bank_user"})
    @GetMapping("money/{uid}")
    public RetResult getMoney(@PathVariable("uid") String uid){
        BankUser bankUser = bankUserService.getById(uid);
        if(bankUser == null ) return RetResponse.makeErrRsp("没有该用户");
        return RetResponse.makeOKRsp(bankUser.getMoney());
    }

    @Authorization({"admin", "bank_user"})
    @PostMapping("search")
    public RetResult searchUser(String username, String phone){
        if(StringUtils.isNotBlank(username)){
            Map<String, String> userNameMap = redisService.hGetAll("user_all_name");
            String res = userNameMap.get(username);
            if(StringUtils.isNotBlank(res))
                return RetResponse.makeOKRsp(res);
        }

        if(StringUtils.isNotBlank(phone)){
            Map<String, String> userPhoneMap = redisService.hGetAll("user_all_phone");
            String res = userPhoneMap.get(phone);
            if(StringUtils.isNotBlank(res))
                return RetResponse.makeOKRsp(res);
        }

        return RetResponse.makeErrRsp("没有该用户");
    }


    @Authorization({"admin", "bank_user"})
    @GetMapping("search/{uid}")
    public RetResult getUserById(@PathVariable("uid") String uid){
        if(StringUtils.isBlank(uid)) return RetResponse.makeErrRsp("uid不能为空");
        BankUser user = bankUserService.getById(uid);
        return user != null ? RetResponse.makeOKRsp(user) : RetResponse.makeErrRsp("用户不存在");
    }


    @Authorization({"admin", "bank_user"})
    @PostMapping("update_head_img/{uid}")
    public RetResult updateHeadImg(MultipartFile file, @PathVariable("uid") String uid) throws IOException {
        String headImgUrl = ossService.upload(file);
        headImgUrl = headImgUrl.replaceAll("https://yulango-user-img.https://oss-cn-beijing.aliyuncs.com/", "");
        BankUser user = bankUserService.getById(uid);
        user.setHeadImgUrl(headImgUrl);
        bankUserService.updateById(user);
        return new RetResult<String>().setCode(RetCode.SUCCESS).setMsg("上传成功").setData(headImgUrl);
    }

    @Authorization({"admin", "bank_user"})
    @PostMapping("change_pwd")
    public RetResult changePwd(HttpServletRequest request, String uid, String code, String phone, String newPwd) {
        if(StringUtils.isBlank(uid)) return RetResponse.makeErrRsp("uid不能为空");
        if(StringUtils.isBlank(code)) return RetResponse.makeErrRsp("验证码不能为空");
        if(StringUtils.isBlank(newPwd)) return RetResponse.makeErrRsp("新的密码不能为空");
        if(StringUtils.isBlank(phone)) return RetResponse.makeErrRsp("手机号不能为空");
        String oldCode = redisService.get(phone + "_msg");

        if(!StringUtils.equals(oldCode, code))
            return RetResponse.makeErrRsp("验证码错误");

        BankUser user = bankUserService.getById(uid);
        if(!StringUtils.equals(user.getPhone(), phone))
            return  RetResponse.makeErrRsp("手机号错误");

        user.setPassword(MD5Util.encoderByMd5(newPwd));
        boolean res = bankUserService.updateById(user);

        executor.execute(() ->{
            String ip = IpUtil.getIpAddr(request);
            if(!ip.matches(RiskConstant.IPV4_REGEX))
                return;
            riskService.checkRemoteChangePwd(uid, ip);
        });


        return res ? RetResponse.makeOKRspMsg("修改成功") : RetResponse.makeErrRsp("修改失败");
    }

    @Authorization({"admin", "bank_user"})
    @PostMapping("/change_pay_pwd")
    public RetResult changePayPwd(HttpServletRequest request, String uid, String code, String phone, String newPayPwd){
        if(StringUtils.isBlank(uid)) return RetResponse.makeErrRsp("uid不能为空");
        if(StringUtils.isBlank(code)) return RetResponse.makeErrRsp("验证码不能为空");
        if(StringUtils.isBlank(newPayPwd)) return RetResponse.makeErrRsp("新的支付密码不能为空");
        if(StringUtils.isBlank(phone)) return RetResponse.makeErrRsp("手机号不能为空");

        String oldCode = redisService.get(phone + "_msg");

        if(!StringUtils.equals(oldCode, code))
            return RetResponse.makeErrRsp("验证码错误");


        BankUser user = bankUserService.getById(uid);
        if(!StringUtils.equals(user.getPhone(), phone))
            return  RetResponse.makeErrRsp("手机号错误");

        user.setPayPassword(MD5Util.encoderByMd5(newPayPwd));
        boolean res = bankUserService.updateById(user);


        executor.execute(() ->{
            String ip = IpUtil.getIpAddr(request);
            if(!ip.matches(RiskConstant.IPV4_REGEX))
                return;
            riskService.checkRemoteChangePayPwd(uid, ip);
        });

        return res ? RetResponse.makeOKRspMsg("修改成功") : RetResponse.makeErrRsp("修改失败");
    }

    @Authorization({"admin", "bank_user"})
    @PostMapping("/change_phone")
    public RetResult changePhone(HttpServletRequest request, String uid, String code, String newPhone){
        if(StringUtils.isBlank(uid)) return RetResponse.makeErrRsp("uid不能为空");
        if(StringUtils.isBlank(code)) return RetResponse.makeErrRsp("验证码不能为空");
        if(StringUtils.isBlank(newPhone)) return RetResponse.makeErrRsp("新的手机号不能为空");

        BankUser user = bankUserService.getById(uid);
        String oldCode = redisService.get(user.getPhone() + "_msg");

        if(!StringUtils.equals(oldCode, code))
            return RetResponse.makeErrRsp("验证码错误");

        if(StringUtils.equals(user.getPhone(), newPhone))
            return  RetResponse.makeErrRsp("无需修改旧的手机号");

        user.setPhone(newPhone);
        boolean res = bankUserService.updateById(user);

        executor.execute(() ->{
            String ip = IpUtil.getIpAddr(request);
            if(!ip.matches(RiskConstant.IPV4_REGEX))
                return;
            riskService.checkRemoteChangePhone(uid, ip);
        });

        return res ? new RetResult<String>().setData(newPhone).setMsg("修改成功").setCode(RetCode.SUCCESS)
                : RetResponse.makeErrRsp("修改失败");
    }




    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, String> userNameMap = redisService.hGetAll("user_all_name");
        if(userNameMap == null || userNameMap.isEmpty()){
            List<BankUser> users = bankUserService.list();
            users.forEach(item ->{
                redisService.hSet("user_all_name", item.getUserName(), item.getId(), TEN_DAY, TimeUnit.MILLISECONDS);
            });
        }

        Map<String, String> userPhoneMap = redisService.hGetAll("user_all_phone");
        if(userPhoneMap == null || userPhoneMap.isEmpty()){
            List<BankUser> users = bankUserService.list();
            users.forEach(item ->{
                redisService.hSet("user_all_phone", item.getPhone(), item.getId(), TEN_DAY, TimeUnit.MILLISECONDS);
            });
        }
    }
}
